// 本文件中包含了2个模块，AD按键和AD滑动变阻器(0-9.5K)
// 用于调节刹车增益

#include "app_key.h"

boolean_t pwm_mode_chg = FALSE;
boolean_t pwm_mode_chg_by_gain = FALSE;

uint8_t r_ad_pwm_duty = 0;

/*
增益数据和车载显示盘上显示增益对应关系
*/
stc_gain_t gain =
{
		0x02, 0x0a,  /* 0.0 , 0.5*/
		0x12, 0x1a,  /* 1.0 , 1.5*/
		0x22, 0x2a,  /* 2.0 , 2.5*/
		0x32, 0x3a,  /* 3.0 , 3.5*/
		0x42, 0x4a,  /* 4.0 , 4.5*/
		0x52, 0x5a,  /* 5.0 , 5.5*/
		0x62, 0x6a,  /* 6.0 , 6.5*/
		0x72, 0x7a,  /* 7.0 , 7.5*/
		0x82, 0x8a,  /* 8.0 , 8.5*/
		0x92, 0x9a,  /* 9.0 , 9.5*/
		0xA2,		/* 10.0 */
		16,			/*index*/
		0,
};  /*刹车增益*/

//增益与最大占空比对应关系表：
uint8_t Gain_tab[21][2] = 
{
	{0x02,0}, /*低频区*/
	{0x0a,0}, /*低频区*/
	{0x12,12},
	{0x1a,17},
	{0x22,22}, /*2.0 = 22%*/
	{0x2a,27}, 
	{0x32,32}, 
	{0x3a,41},
	{0x42,50},
	{0x4a,55},
	{0x52,60},
	{0x5a,65},
	{0x62,70},
	{0x6a,77},
	{0x72,85},
	{0x7a,88},
	{0x82,90}, /* Gain8 占空比3.6ms */
	{0x8a,92},
	{0x92,93},
	{0x9a,94},
	{0xa2,95},
};

boolean_t  first_Acc_ON = FALSE;
boolean_t  first_Acc_ON_2pwm = FALSE;
boolean_t  first_Acc_OFF= FALSE;

stc_slide_res_t slide_res;

uint8_t miss_menu_cnt = 0;  //菜单消失计数
uint8_t brake_pwm_flag = 0;  //刹车输出标志

void PULSE_Pin_Init(void)
{
	stc_gpio_cfg_t stcGpioCfg;
    
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    
    ///< 端口方向配置->输出 
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口上下拉配置-> none
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;
	stcGpioCfg.enDrv = GpioDrvH;
	stcGpioCfg.enCtrlMode = GpioAHB;
	
    Gpio_Init(GpioPortA, GpioPin0, &stcGpioCfg);
	Gpio_Init(GpioPortA, GpioPin1, &stcGpioCfg);
	
    Gpio_ClrIO(GpioPortA, GpioPin0); 
	Gpio_ClrIO(GpioPortA, GpioPin1); 
	
}

/*计算动态临界点*/
void Calculate_ratio(void)
{
	slide_res.critical_Rvalue_AB = 100;
	slide_res.critical_Rvalue_BC = 100; 
}

void deal_key(uint8_t key)
{
	if((key == KEY_UP) && (gain.index < 20))
	{
		if(!first_Acc_ON)
			gain.index++;
	}
	if ((key == KEY_DOWN) && (gain.index > 0))
	{
		if(!first_Acc_ON)
			gain.index--;
	}
	
	Update_BrakeGain_buffer();	
	gain.panel_disp = TRUE;
	miss_menu_cnt = 0;
	if(first_Acc_ON) /*按键已激活*/
	{
		first_Acc_ON = FALSE;
	}
}

/*
此按键为2个AD按键，公用一个IO PA0 检测口
长按累加功能,第二版加入
*/	uint32_t sum = 0;

void key_scan(void)
{
	uint8_t key = KEY_NONE;
	static uint8_t last_key = 0, filter_key=0;
	static uint16_t filter_cnt=0;
	uint32_t sum = 0;

	for(uint8_t i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult0[i];
	}
	sum = sum/ADC_LOOP_NUM;
	if(sum > RANGE_DOWN_KEY1 && sum < RANGE_UP_KEY1 )
	{
		key = KEY_UP;	
	}
	else if(sum < RANGE_UP_KEY2 ) 
    {
		key = KEY_DOWN;	
	}
	
	if (key == filter_key)
	{
		if (filter_cnt++ <= 500)
		{
			return;
		}
	}
	else
	{
		filter_cnt = 0;
		filter_key = key;
		return;
	}
	
	if (key == last_key)
	{
		if ((key != KEY_NONE) && (APP_CAN.key_cnt >= 100)) //长按0.5秒  
		{
			APP_CAN.key_cnt = 0;
			deal_key(key);
		}
		return;	
	}
	last_key = key;
	APP_CAN.key_cnt = 0;
	
	// 必须在return后面,确保按键累加只加一次
	if (key != KEY_NONE)
	{
		deal_key(key);
	}
}

void Slide_resistor_detect(void)
{		
	int sum = 0;	
	for(int i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult5[i];
	}
	slide_res.Rvalue = sum/ADC_LOOP_NUM;  /* slide_res.Rvalue 值越小,PWM占空比越大*/
}


void Load_Current_detect(void)
{
	int adc_value = 0;	
	int sum = 0;
	for(int i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult2[i];
	}
	adc_value = sum/ADC_LOOP_NUM;
	
	if( adc_value > 500) /*过流,总电流700mA左右*/
	{
		// 拉低IO_INH,断电不起作用,看硬件
		//	
		// 因该拉低2路PWM引脚为低电平.		
		// TJA1043_Goto_Sleep();	
		//PULSE_Pin_Init();		
	}
}

/*******************************************************************************
**函数信息 ：void Update_BrakeGain_buffer()
**功能描述 ：CAN发送一帧刹车增益报文,发送周期为100ms
**输入参数 ：stcTxFrame
**输出参数 ：None
**备     注 ：exp data 445   10 A2 00 00 00 00 00 00 
5.21 测试 byte0 = 0xA8 . if gain < 12 , byte0 = 0x28
*******************************************************************************/
void Update_BrakeGain_buffer(void)
{
	TxFrame_Gain.Data[1] = gain.Tab[gain.index]; // 需要断电保存	
	
	if (gain.index != Flash_ReadConfig())
		Flash_WriteConfig(gain.index);	
}

/*检测 acc off -> acc on*/
void ACC_Status_Check(void)
{
    static en_ACC_Status last_status = Off;
	
	if(last_status == Off)
	{
		if(ACC_Status == On)
		{
			last_status = ACC_Status;
			first_Acc_ON = TRUE;
			first_Acc_ON_2pwm = TRUE;	
		}
	}
	else
	{
		if(ACC_Status == Off)
		{
			last_status = ACC_Status;	
			first_Acc_OFF = TRUE;
		}
	}	
}


/*********************************************************************
**函数信息 ：void App_PWM_out_init()
**功能描述 ：上电后确认pwm输出状态以及初始化
**输入参数 ：void
**输出参数 ：void
**备    注 ：
********************************************************************/
void App_PWM_out_init(void)
{
	delay1ms(100); /*等待ad转换完成*/
	
	Slide_resistor_detect();
	
	int res_delta = SLIDE_RES_AD_MAX - slide_res.Rvalue;
	
	/*这里注意,Gain增益保存在Flash中,先读falsh,OK 赋值给全局变量;*/
	if( 0xff != Flash_ReadConfig())
	{
		gain.index = Flash_ReadConfig();
	}
	APP_struct_init();			
}


void APP_struct_init(void)
{
	TxFrame_Gain.StdID = CAN_ID_GAIN;
	TxFrame_Gain.Data[0] = 0x00; // or 0x28
	TxFrame_Gain.Data[1] = gain.Tab[gain.index]; // 需要断电保存
	TxFrame_Gain.Data[2] = 0x00;	
	TxFrame_Gain.Data[3] = 0x00;	
	TxFrame_Gain.Data[4] = 0x00;	
	TxFrame_Gain.Data[5] = 0x00;
	TxFrame_Gain.Data[6] = 0x00;
	TxFrame_Gain.Data[7] = 0x00;	
	
	TxFrame_Keepalive.StdID = CAN_ID_KEEPALIVE;
	TxFrame_Keepalive.Data[0] = 0xC0; 
	TxFrame_Keepalive.Data[1] = 0x00; 
	TxFrame_Keepalive.Data[2] = 0xFF;	
	TxFrame_Keepalive.Data[3] = 0xFF;	
	TxFrame_Keepalive.Data[4] = 0xFF;	
	TxFrame_Keepalive.Data[5] = 0xFF;
	TxFrame_Keepalive.Data[6] = 0xFF;
	TxFrame_Keepalive.Data[7] = 0xFF;
}

void CAN_BUS_Process(void)
{
	static int cnt = 0;
	static int cnt2 = 0;
	static int cnt3 = 0;
	
	 if(APP_CAN.CANSendFlag) /*100ms*/
	 {
		APP_CAN.CANSendFlag = FALSE;
		 
/*
1. 当gain > 1 时. slide to C , byte0 的变化 0xA8 -0.1s--> 0x28 -1s-> 0x20 --3s-> 0x00 	
2. 当gain <= 1 时. slide to C , byte0 的变化 0x28 -1s-> 0x20 --3s-> 0x00 		
*/	
	
		if(gain.panel_disp)  //按键触发的
		 {
				if(pwm_mode_chg_by_gain) //滑组
				{				
						if(gain.index > 1) 
						{
								TxFrame_Gain.Data[0] = 0xa8;
						}
						else
						{
								TxFrame_Gain.Data[0] = 0x28;					
						}
						gain.panel_disp = FALSE;
						pwm_mode_chg_by_gain = FALSE;
				}
				else
				{			
					if(PWM_Mode == PULSE)
					{
						TxFrame_Gain.Data[0] = 0x08;
						miss_menu_cnt++;		
						if(miss_menu_cnt >= 12)
						{
							gain.panel_disp = FALSE;	
							TxFrame_Gain.Data[0] = 0x00;
							miss_menu_cnt = 0; 
						}				
					}
				}	
				
				pwm_mode_chg = 0;
				cnt2 = 0;
				cnt3 = 0;
			goto CAN_SEND;
		 }
		 
		if(gain.index > 1)  /* 通过滑动变阻器改变 PWM-MODE*/
		{		
			if(pwm_mode_chg)
			{
				 if(PWM_Mode == PULSE) // 滑组输出A8 -> 28 ->-(1s)--> 20 ->-(3s)-->- 00
				 {
					   if (brake_pwm_flag)  //刹车输出80->00
 					   {
						   TxFrame_Gain.Data[0] = 0x00; 
							pwm_mode_chg = 0;
					   }
					   else
                       {
						   TxFrame_Gain.Data[0] = 0x28;
						   cnt2++;
						   if(cnt2 > 10 && cnt2 <= 40) /*1s*/
						   {
								TxFrame_Gain.Data[0] = 0x20; 
						   }
						   if(cnt2 > 40) /*1s + 3s*/
						   {
								TxFrame_Gain.Data[0] = 0x00; 
								pwm_mode_chg = 0;
								cnt2 = 0;
						   }
					   }
				 }	
				 if(PWM_Mode == PWM) 
				 {
					if (brake_pwm_flag)
						TxFrame_Gain.Data[0] = 0x80;
					else
						TxFrame_Gain.Data[0] = 0xA8;	
					 
					pwm_mode_chg = 0;
					cnt2 = 0;
				 }
			}
		}
		else   // gain <= 1,滑动变阻器无法改变pwm-mode
		{
			if(slide_res.Rvalue < 60)
			  {
				  if(TxFrame_Gain.Data[0]) 
				  {
						  delay1ms(5);
						  if(slide_res.Rvalue < 60)
						  {					
							   TxFrame_Gain.Data[0] = 0x20;
							   cnt3++;
							   if(cnt3 > 30) /*+ 3s*/
							   {
									TxFrame_Gain.Data[0] = 0x00; 
									cnt3 = 0;
							   }		  
						  }  
				  }	
			  }	
			 else
			 {
				  TxFrame_Gain.Data[0] = 0x28;
			 }	
	   }
		
	   CAN_SEND:
	   CAN_send_Frame(&TxFrame_Gain, 8);
	 }
	 
	 if(APP_CAN.CAN_keepalive_SendFlag) /*心跳包数据,1s发送一次*/
	 {
		APP_CAN.CAN_keepalive_SendFlag = FALSE;	
		CAN_send_Frame(&TxFrame_Keepalive, 8);
	 }
		
	if(APP_CAN.BusErrorFlag)
	{
		APP_CAN.BusErrorFlag = FALSE;
		M0P_CAN->CFG_STAT = 0x00;
	}
}

/*
1. 切换pwm
0. 切换puls
return 0 未切换 1.切换成功
*/
int pwm_change_pulse(uint8_t on)
{	
	if (on)
	{
		if(PWM_Mode != PWM)
		{
			PULSE_Pin_Init();				
			Reset_RstPeripheral0(ResetMskBaseTim);
			BSP_PWM_Config();// 切换到PWM模式
			PWM_Mode = PWM;
			pwm_mode_chg = TRUE;
		}
		return 1;
	}
	else 
	{ // 切换到脉冲模式 
		if(PWM_Mode != PULSE)
		{
			PULSE_Pin_Init();				
			Reset_RstPeripheral0(ResetMskBaseTim);
			BSP_2Comp_PWM_Config();	
			PWM_Mode = PULSE;
			pwm_mode_chg = TRUE;
		}
		return 1;
	}
	return 0;
}
#if 0
void shutdown_pwm()
{
	PULSE_Pin_Init();				
	Bt_M23_EnPWM_Output(TIM0, FALSE, FALSE);    //TIM0 端口输出使能  
	Bt_M23_Stop(TIM0);
}
#endif

uint8_t get_brake(unsigned int brake)
{
//增益： 5，刹车深度：7D 05 00，灯半亮
//增益： 6，刹车深度：7D 04 A0，灯半亮
//增益： 7，刹车深度：7D 04 50，灯半亮
//增益： 8，刹车深度：7D 04 00，灯半亮
//增益： 9，刹车深度：7D 03 A0，灯半亮
//增益：10，刹车深度：7D 03 50，灯半亮
		if (((brake > 22) && (gain.index == 20)) || \
					((brake > 24) && ((gain.index == 19)||(gain.index == 18))) || \
					((brake > 26) && ((gain.index == 17)||(gain.index == 16))) || \
					((brake > 28) && ((gain.index == 15)||(gain.index == 14))) || \
					((brake > 30) && ((gain.index == 13)||(gain.index == 12))) || \
					((brake > 33) && ((gain.index == 11)||(gain.index == 10))) || \
					((brake > 25) && (gain.index < 10)))
		{
				if (gain.index < 10)//短踩小于8秒，大于等于5增益才会输出
				{
						brake = 0;
				}
				else if (gain.index < 14)   //短踩小于8秒，刹车在5.0-7.0, 保持最小输出
						brake = 9;
				else   //增益7.0以上，深度有影响
				{
					if (gain.index == 20)
						brake = 9+(brake-22)/3;
					else if (gain.index == 18|| gain.index == 19)
						brake = 9+(brake-24)/3;
					else if (gain.index == 17|| gain.index == 16)
						brake = 9+(brake-26)/3;
					else if(gain.index == 15|| gain.index == 14) 
						brake = 9+(brake-28)/3;
				}
				
				if (APP_CAN.brake_cnt >= 200*6 && gain.index > 0) //长踩大于8秒，输出20
						brake = 50;
		}
		else
		{
				brake = 0;
				APP_CAN.brake_cnt = 0;
		}
		return brake;
}


void pwm_output1(void)
{
		unsigned int r_ad = 0;   /*百分比已扩大100倍*/
		unsigned int brake_signal = 0;   //0或者6.25%
		unsigned int brake = 0;  /*百分比已扩大100倍*/

		if(first_Acc_OFF)
		{
			first_Acc_OFF = FALSE;
			PULSE_Pin_Init();				
			Reset_RstPeripheral0(ResetMskBaseTim);	
		}
		
		if(first_Acc_ON_2pwm)
		{
			first_Acc_ON_2pwm =  FALSE;
			if(PWM_Mode == PWM)
			{
				BSP_PWM_Config();// PWM模式		
			}
			else
			{
				BSP_2Comp_PWM_Config();// PULSE模式	
			}
		}
		
		if(ACC_Status == Off) //acc off全部关掉
		{
			return;
		}
		
		/*
		if (APP_CAN.brake_signal) 
		{
			brake_signal = 20;
		}
		else
		{
			brake_signal = 0;
		}*/
		
	// 刹车深度占空比转换
	#ifdef VERSION_BRAKE_DEEP
		brake = 100*(APP_CAN.brake_value)/0xf00;
		brake = get_brake(brake);
	#endif	
		
		//滑组占空比转化
		if(slide_res.Rvalue > 2260)  /* A段区间,PWM不变化,按最大值执行*/
		{
				slide_res.Rvalue = 2260;
				r_ad_pwm_duty = Gain_tab[gain.index][1];
		}	
		else
		{	 	
				r_ad_pwm_duty = Gain_tab[gain.index][1]*(slide_res.Rvalue)/2260;
		}
		r_ad = 100*(slide_res.Rvalue)/(2260);
		

		if (r_ad < 7 && brake_signal < 7 && brake < 7)
		{
				pwm_change_pulse(0);
		}
		else
		{				
			if(brake > r_ad)  // 电子刹车优先级最高,不收gain影响;
			{
					if(brake > 95)
							brake = 95;
					brake_pwm_flag = 1;
					pwm_change_pulse(1);
					BSP_PWM_SetDuty(brake); 
			}
			else
			{			
					if (gain.index < 2)
					{
							pwm_change_pulse(0);
							pwm_mode_chg_by_gain = TRUE;
					}
					else
					{
							brake_pwm_flag = 0;
							pwm_change_pulse(1);
							if (r_ad_pwm_duty < 7) //保证最小占空比起跳
							{
								r_ad_pwm_duty = 7;
							}
							if(r_ad_pwm_duty > 96)
							{
								r_ad_pwm_duty = 96;
							}
							BSP_PWM_SetDuty(r_ad_pwm_duty); 
					}
			}
		}
}


